package com.weigecoder.warehouse.controller;

import com.google.code.kaptcha.Producer;
import com.weigecoder.warehouse.entity.Auth;
import com.weigecoder.warehouse.entity.LoginUser;
import com.weigecoder.warehouse.entity.Result;
import com.weigecoder.warehouse.entity.User;
import com.weigecoder.warehouse.service.AuthService;
import com.weigecoder.warehouse.service.UserService;
import com.weigecoder.warehouse.utils.CurrentUser;
import com.weigecoder.warehouse.utils.DigestUtil;
import com.weigecoder.warehouse.utils.TokenUtils;
import com.weigecoder.warehouse.constant.WarehouseConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

@RestController
public class LoginController {

    @Resource(name = "captchaProducer")
    private Producer producer;
    @Autowired
    private UserService userService;
    @Autowired
    private AuthService authService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private TokenUtils tokenUtils;


    /**
     * 生成验证码图片
     *
     * @param response
     */
    @GetMapping("/captcha/captchaImage")
    public void getCaptchaImage(HttpServletResponse response) {
        ServletOutputStream outputStream = null;
        try {
            //禁止浏览器缓存验证码图片的响应头
            response.setDateHeader("Expires", 0);
            response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
            response.addHeader("Cache-Control", "post-check=0, pre-check=0");
            response.setHeader("Pragma", "no-cache");
            //设置响应正文image/jpeg
            response.setContentType("image/jpeg");

            //生成验证码的文本
            String text = producer.createText();
            //使用验证码文本生成验证码图片
            BufferedImage image = producer.createImage(text);
            String imageCode_key = text.toUpperCase();
            System.out.println(imageCode_key+"===================================================");
            //将验证码文本作为键和值保存到redis -- 设置键的过期时间为5分钟
            stringRedisTemplate.opsForValue().set(imageCode_key, imageCode_key, WarehouseConstants.CAPTCHA_IMAGE_EXPIRE, TimeUnit.SECONDS);

            outputStream = response.getOutputStream();
            // 将验证码图片响应给前端
            ImageIO.write(image, "jpg", outputStream);
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 用户登录
     *
     * @param loginUser
     * @return
     */
    @PostMapping("/login")
    public Result login(@RequestBody LoginUser loginUser) {
        String verificationCode = loginUser.getVerificationCode().toUpperCase();
        /**
         校验验证码
         */
        if (!stringRedisTemplate.hasKey(verificationCode)) {
            return Result.err(Result.CODE_ERR_BUSINESS, "验证码不正确！");
        }
        /**
         校验用户名密码
         */
        User user = userService.findUserByCode(loginUser.getUserCode());
        if (user != null) {//查到了用户
            //查到的用户状态是已审核
            if (user.getUserState().equals(WarehouseConstants.USER_STATE_PASS)) {
                //将用户录入的密码进行加密
                String password = DigestUtil.hmacSign(loginUser.getUserPwd());
                //查到的用户的密码和用户录入的密码相同
                if (password.equals(user.getUserPwd())) {
                    //生成token并响应给前端
                    CurrentUser currentUser = new CurrentUser(user.getUserId(), user.getUserCode(), user.getUserName());
                    String token = tokenUtils.loginSign(currentUser, user.getUserPwd());
                    return Result.ok("登录成功！", token);
                } else {
                    //查到的用户的密码和用户录入的密码不同
                    return Result.err(Result.CODE_ERR_BUSINESS, "用户名或密码不正确！");
                }
            } else {
                //查到的用户状态是未审核
                return Result.err(Result.CODE_ERR_BUSINESS, "用户未审核！");
            }
        } else {
            //没有查到用户
            return Result.err(Result.CODE_ERR_BUSINESS, "该用户不存在！");
        }
    }

    /**
     * 获取当前登录用户信息的url接口/curr-user
     *
     * @RequestHeader(WarehouseConstants.HEADER_TOKEN_NAME) String clientToken
     * 将请求头Token的值即前端归还的token,赋值给请求处理方法的参数String clientToken
     */
    @GetMapping("/curr-user")
    public Result currUser(@RequestHeader(WarehouseConstants.HEADER_TOKEN_NAME) String clientToken) {
        //从前端归还的token中解析出当前登录用户的信息
        CurrentUser currentUser = tokenUtils.getCurrentUser(clientToken);
        return Result.ok(currentUser);
    }

    /**
     * 加载当前登录用户权限(菜单)树的url接口/user/auth-list
     *
     * @RequestHeader(WarehouseConstants.HEADER_TOKEN_NAME) String clientToken
     * 将请求头Token的值即前端归还的token,赋值给请求处理方法的参数String clientToken
     */
    @GetMapping("/user/auth-list")
    public Result authList(@RequestHeader(WarehouseConstants.HEADER_TOKEN_NAME) String clientToken) {
        //从前端归还的token中解析出当前登录用户的信息
        CurrentUser currentUser = tokenUtils.getCurrentUser(clientToken);
        //根据用户id查询用户权限(菜单)树
        List<Auth> authTreeList = authService.findAuthTreeByUserId(currentUser.getUserId());
        //响应
        return Result.ok(authTreeList);
    }

    /**
     * 登出的url接口/logout
     *
     * @RequestHeader(WarehouseConstants.HEADER_TOKEN_NAME) String clientToken
     * 将请求头Token的值即前端归还的token,赋值给请求处理方法的参数String clientToken
     */
    @DeleteMapping("/logout")
    public Result logout(@RequestHeader(WarehouseConstants.HEADER_TOKEN_NAME) String clientToken) {
        //从redis移除token
        stringRedisTemplate.delete(clientToken);
        return Result.ok();
    }


}
